#include"DSP_cluster.h"
#include<cstdlib>
#include<ctime>
#include<iostream>

int random_int(int min, int max) {
    static bool first = true;
    if (first) {
        srand((unsigned int)time(NULL)); //seeding for the first time only!
        first = false;
    }
    return min + rand() % (( max + 1 ) - min);
}

bool DSP_cluster::store_instruction(addr_size_t addr, instruction* instr, int para_nums, addr_size_t head_addr) {
    return this->instruction_mem->store_instruction(addr, instr, para_nums,head_addr);
}

instr_unit* DSP_cluster::get_instr(addr_size_t addr) {
    return this->instruction_mem->get_instr(addr);
}

bool DSP_cluster::store_function(std::string func_name, addr_size_t head_addr, addr_size_t end_addr){
    return this->instruction_mem->store_function(func_name, head_addr, end_addr);
}
    
addr_unit* DSP_cluster::get_func(std::string func_name){
    return this->instruction_mem->get_func(func_name);

};

int DSP_cluster::group_create(int num) {
    //默认创建的线程组不带参数
    std::vector<int> node_indices; //记录分配给该线程组的DSP核索引
    GroupEngine* ge = new GroupEngine();
    for (int i = 0; i < this->DSP_nodes->size(); i++) {
        if (this->DSP_nodes->at(i) == nullptr) {
            if (num > 0) {
                node_indices.push_back(i);
                this->DSP_nodes->at(i) = new DSP_node(this->instruction_mem, this->GSM);
                ge->add_node_engine(this->DSP_nodes->at(i)->get_engine());
                num--;
            } else {
                break;
            }
        }
    }
    if (num == 0) {
        //TODO:返回创建成功的线程组id，暂时返回一个随机数模拟，后续确定如何设置线程组id
        int res = random_int(1, 100);
        (*this->thread_id_to_nodes_map)[res] = node_indices; //将线程组id和对应的DSP核索引存入映射表
        (*this->thread_id_to_status_map)[res] = 0; //将线程组状态设置为空闲，此时创建了线程组，但未分配要执行的函数
        this->cluster_engine->add_group_engine(res, ge);
        return res; //成功创建num个线程
    } else {
        return -1; //未能成功创建num个线程，可能是因为DSP核数量不足
    }
}

// addr_size_t get_addr_from_func_name(const char* func_name) {
//     //TODO:根据函数名获取地址，暂时返回一个随机数模拟
//     //TODO:后续考虑设计一个函数名->地址的映射表
//     //TODO:尚士喆考虑如何在指令解析阶段获取函数名和对应地址
//     return random_int(1, 100);
// }

int DSP_cluster::group_create(int num, char *func_name, int scalarArgs, int ptrArgs, uint64_t *argArray) {
    //创建的线程组带参数
    addr_unit* au = this->get_func(func_name);
    if (au == nullptr) {
        return -1; //未找到对应的函数名，无法创建线程组
    }   
    addr_size_t start_addr = au->head_addr;
    addr_size_t end_addr = au->end_addr;
    std::cout << "Creating group for function: " << func_name << " with start address: " << std::hex << start_addr << " and end address: " << end_addr << std::dec << std::endl;
    if (start_addr == 0 || end_addr == 0 || start_addr >= end_addr) {
        return -1; //函数地址不合法，无法创建线程组
    }
    std::vector<int> node_indices; //记录分配给该线程组的DSP核索引
    GroupEngine* ge = new GroupEngine();
    for (int i = 0; i < this->DSP_nodes->size(); i++) {
        if (this->DSP_nodes->at(i) == nullptr) {
            if (num > 0) {
                std::cout << "Allocating DSP node index: " << i << " for the group." << std::endl;
                node_indices.push_back(i);
                this->DSP_nodes->at(i) = new DSP_node(this->instruction_mem, this->GSM, start_addr);
                //先单独设置该DSP核的End_PC指针，避免修改构造函数，引入后续重构的复杂性
                this->DSP_nodes->at(i)->get_engine()->set_End_PC(end_addr);
                ge->add_node_engine(this->DSP_nodes->at(i)->get_engine());
                num--;
            } else {
                break;
            }
        }
    }
    if (num == 0) { 
        //TODO:返回创建成功的线程组id，暂时返回一个随机数模拟，后续确定如何设置线程组id
        int res = random_int(1, 100);
        (*this->thread_id_to_nodes_map)[res] = node_indices; //将线程组id和对应的DSP核索引存入映射表
        (*this->thread_id_to_status_map)[res] = 1; //将线程组状态设置为运行中
        this->cluster_engine->add_group_engine(res, ge);
        std::cout << "Executing group engine for thread ID: " << res << std::endl;
        ge->Execute(); //立即执行该线程组的任务
        std::cout << "Group engine execution completed for thread ID: " << res << std::endl;
        //TODO:此处为后续并行设计留出接口，目前串行版本中thread_id_to_status_map的状态值无实际意义
        (*this->thread_id_to_status_map)[res] = 0; //将线程组状态设置为空闲
        return res; //成功创建num个线程
    } else {
        return -1; //未能成功创建num个线程，可能是因为DSP核数量不足
    }
}

int DSP_cluster::group_masked_create(unsigned int pmask, char *func_name, int scalarArgs, int ptrArgs, uint64_t *argArray) {
    //根据pmask创建线程组
    addr_unit* au = this->get_func(func_name);
    if (au == nullptr) {
        return -1; //未找到对应的函数名，无法创建线程组
    }   
    addr_size_t start_addr = au->head_addr;
    addr_size_t end_addr = au->end_addr;
    if (start_addr == 0 || end_addr == 0 || start_addr >= end_addr) {
        return -1; //函数地址不合法，无法创建线程组
    }
    std::vector<int> node_indices; //记录分配给该线程组的DSP核索引
    GroupEngine* ge = new GroupEngine();
    for (int i = 0; i < this->DSP_nodes->size(); i++) {
        if ((pmask & (1 << i)) != 0) { //检查pmask的第i位是否为1
            if (this->DSP_nodes->at(i) == nullptr) {
                node_indices.push_back(i);
                this->DSP_nodes->at(i) = new DSP_node(this->instruction_mem, this->GSM, start_addr);
                //先单独设置该DSP核的End_PC指针，避免修改构造函数，引入后续重构的复杂性
                this->DSP_nodes->at(i)->get_engine()->set_End_PC(end_addr);
                ge->add_node_engine(this->DSP_nodes->at(i)->get_engine());
            } else {
                //该DSP核已被占用，无法创建线程组
                return -1;
            }
        }
    }
    //TODO:返回创建成功的线程组id，暂时返回一个随机数模拟，后续确定如何设置线程组id
    int res = random_int(1, 100);
    (*this->thread_id_to_nodes_map)[res] = node_indices; //将线程组id和对应的DSP核索引存入映射表
    (*this->thread_id_to_status_map)[res] = 1; //将线程组状态设置为运行中
    this->cluster_engine->add_group_engine(res, ge);
    ge->Execute(); //立即执行该线程组的任务 
    //TODO:此处为后续并行设计留出接口，目前串行版本中thread_id_to_status_map的状态值无实际意义
    (*this->thread_id_to_status_map)[res] = 0; //将线程组状态设置为空闲
    return res; //成功创建num个线程
}

int DSP_cluster::group_exec(int thread_id, char *func_name, int scalarArgs, int ptrArgs, uint64_t *argArray) {
    //执行指定线程组的任务
    auto it = this->thread_id_to_nodes_map->find(thread_id);
    if (it != this->thread_id_to_nodes_map->end()) {
        addr_unit* au = this->get_func(func_name);
        if (au == nullptr) {
            return -1; //未找到对应的函数名，无法创建线程组
        }   
        addr_size_t start_addr = au->head_addr;
        addr_size_t end_addr = au->end_addr;
        if (start_addr == 0 || end_addr == 0 || start_addr >= end_addr) {
            return -1; //函数地址不合法，无法创建线程组
        }
        for (int node_index : it->second) {
            if (this->DSP_nodes->at(node_index) != nullptr) {
                //设置该DSP核的PC指针到指定的函数地址
                this->DSP_nodes->at(node_index)->get_engine()->set_PC(start_addr);
                this->DSP_nodes->at(node_index)->get_engine()->set_End_PC(end_addr);
                continue;
            } else {
                return -1; //该DSP核不存在，无法执行线程组任务
            }
        }
        (*this->thread_id_to_status_map)[thread_id] = 1; //将线程组状态设置为运行中
        this->cluster_engine->get_group_engine(thread_id)->Execute(); //执行该线程组的任务
        //TODO:此处为后续并行设计留出接口，目前串行版本中thread_id_to_status_map的状态值无实际意义
        (*this->thread_id_to_status_map)[thread_id] = 0; //将线程组状态设置为空闲
        return 0; //成功执行线程组任务
    } else {
        return -1; //未找到对应的线程组id
    }
}

int DSP_cluster::group_get_status(int thread_id) {
    auto it = this->thread_id_to_nodes_map->find(thread_id);
    if (it != this->thread_id_to_nodes_map->end()) {
        //获取线程组状态
        return (*this->thread_id_to_status_map)[thread_id];
    } else {
        return -1; //未找到对应的线程组id
        //处于未创建状态
    }
}

int DSP_cluster::group_destroy(int thread_id) {
    auto it = this->thread_id_to_nodes_map->find(thread_id);
    if (it != this->thread_id_to_nodes_map->end()) {
        //销毁指定线程组，释放对应的DSP核
        for (int node_index : it->second) {
            if (this->DSP_nodes->at(node_index) != nullptr) {
                delete this->DSP_nodes->at(node_index);
                this->DSP_nodes->at(node_index) = nullptr;
                continue;
            } else {
                return -1; //该DSP核不存在，无法销毁线程组
            }
        }
        this->thread_id_to_nodes_map->erase(it); //从映射表中移除该线程组id
        this->thread_id_to_status_map->erase(thread_id); //从状态映射表中移除该线程组id
        return 0; //成功销毁线程组
    } else {
        return -1; //未找到对应的线程组id
    }
}
